﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleRest.Core
{
    /// <summary>
    /// Optionally allows developer to extend the REST pipeline at a service level.  When a valid service extends this class it provides the developer with the opportunity
    /// to override methods to: perform actions before a method is invoked, perform actions after a method is invoked, provide error handling for a method exceptions, 
    /// gains visibility into the request object, gains the ability to specify operation mappings, and more.
    /// </summary>
    public abstract class ServiceBase
    {
        internal List<IOperationMappingHandler> _mappings = new List<IOperationMappingHandler>();
        /// <summary>
        /// List of operation mappings specified for the associates service.
        /// </summary>
        protected IEnumerable<IOperationMappingHandler> Mappings
        {
            get
            {
                return _mappings;
            }
        }

        internal bool _isReusable
        {
            get
            {
                return this.IsReusable;
            }
        }
        /// <summary>
        /// Determines if this service is reusable.  When set to true there will ever only 1 instance of this class created and cached to increase performance.
        /// </summary>
        protected virtual bool IsReusable
        {
            get
            {
                return true;
            }
        }

        internal IHttpRequestMessage _request;
        /// <summary>
        /// REST pipeline request.
        /// </summary>
        protected IHttpRequestMessage Request
        {
            get
            {
                return _request;
            }
        }

        internal IEnumerable<Operation> _registeredOperations;
        /// <summary>
        /// A list of registered operations for this service.
        /// </summary>
        protected IEnumerable<Operation> RegisteredOperations
        {
            get
            {
                return _registeredOperations;
            }
        }

        /// <summary>
        /// Executed right before any operation on this service gets invoked.
        /// </summary>
        /// <param name="targetOperation"></param>
        public virtual void OperationPreExecution(Operation targetOperation) { }
        /// <summary>
        /// Executed right after any operation on this service gets invoked.
        /// </summary>
        /// <param name="targetOperation"></param>
        /// <param name="value"></param>
        public virtual void OperationPostExecution(Operation targetOperation, object value) { }
        /// <summary>
        /// Executed directly after an exception occurs at the operation level.  This exception will still bubble up to the error handler set
        /// by the service configuration.
        /// </summary>
        /// <param name="targetOperation"></param>
        /// <param name="ex"></param>
        public virtual void OperationExecutionException(Operation targetOperation, Exception ex) { }

        /// <summary>
        /// Adds operation mapping for this particular service.
        /// </summary>
        /// <param name="mapping"></param>
        protected void AddMapping(IOperationMappingHandler mapping)
        {
            this._mappings.Add(mapping);
        }
    }
}
